package com.dhp.security.filter;

import com.dhp.security.utils.TokenUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.util.StringUtils;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * @ClassName: TokenAuthenticationFilter
 * @Description: 授权过滤器
 * @Author: dhp
 * @Date: 2020/12/5 21:42
 * @Version: v1.0
 */
public class TokenAuthenticationFilter  extends BasicAuthenticationFilter {
    private RedisTemplate redisTemplate;

    public TokenAuthenticationFilter(AuthenticationManager authenticationManager,RedisTemplate redisTemplate) {
        super(authenticationManager);
        this.redisTemplate = redisTemplate;
    }

    //过滤请求，判断是否登录
    //如果token正确就正常放行，如果token没有或者不正确就提前return
    @Override
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        logger.info("================="+req.getRequestURI());
        //如果token没有或者不正确就提前return（等于是判定为登录失败了）
        String token = req.getHeader("token");
        if(null == token){
            logger.info("token is not exist,authorization failure");
            chain.doFilter(req, res);
            return;
        }

        //根据token获取到（用户名 密码 权限）
        UsernamePasswordAuthenticationToken authentication = getAuthentication(token);

        //如果token正确，且能获取到（用户名 密码 权限),将Authentication写入SecurityContextHolder中供后序使用
        if (authentication != null) {
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }

        //最终让请求继续走下去
        chain.doFilter(req, res);
    }

    //最终通过token，获取用户名，再通过用户名获取到权限，完成授权操作
    private UsernamePasswordAuthenticationToken getAuthentication(String token) {
        //通过token工具类把取到的token解析，得到用户名
        String userName = TokenUtils.getUserNameFromToken(token);
        if(userName.isEmpty()){
            logger.info("token is error");
            return null;
        }

        //以用户名为key，去redis里面取值（该用户的权限）
        List<String> permissionValueList = (List<String>) redisTemplate.opsForValue().get(userName);
        if(null == permissionValueList){
            logger.info("this user has no authorization");
            return null;
        }

        Collection<GrantedAuthority> authorities = new ArrayList<>();
        for(String permissionValue : permissionValueList) {
            if(StringUtils.isEmpty(permissionValue)) continue;

            SimpleGrantedAuthority authority = new SimpleGrantedAuthority(permissionValue);
            authorities.add(authority);
        }
        System.out.println(authorities.toString());
        return new UsernamePasswordAuthenticationToken(userName, token, authorities);
    }
}
